package com.company.singleton;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.company.generic.Book;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

/**
 * 单例
 */
@Slf4j
public final class Singleton {
    //用于缓存当前已经创建过的类
    private static final Map<String, Object> pool = new HashMap<>();

    /**
     * 通过这个方法可以创建单例
     * @param clazz
     * @param args
     * @param <T>
     * @return
     */
    public static <T> T get(Class<T> clazz, Object... args) throws IllegalAccessException, InstantiationException {
        Assert.notNull(clazz, "类类型不应该为空！");
        //log.info(args.getClass() instanceof ArrayTyp);
        //log.info(clazz.toGenericString()+"---"+args);
        //log.info(clazz.toString()+"---"+args);
        //将类名和参数拼接，并把拼接后的字符串作为缓存池的键
        final String key = buildKey(clazz.getName(), args);
        log.info(key);
        T o = (T) pool.get(key);
        if (o == null) {
            //没有获取到值，创建
            synchronized (Singleton.class) {
                o = (T) pool.get(key);
                if (o == null) {
                    o = ReflectUtil.newInstance(clazz, args);
                    pool.put(key, o);

                }

            }
        }
        return o;


    }



    public static <T> T get2(Class<T> clazz, Object... args) throws IllegalAccessException, InstantiationException {
        Assert.notNull(clazz, "错误");
        final String key = buildKey(clazz.getName(), args);
        Object o = pool.get(key);
        if (o == null) {
            synchronized (Singleton.class) {
                o = pool.get(key);
                if (o == null) {

                    o = ReflectUtil.newInstance(clazz, args);
                    pool.put(key, o);
                }

            }

        }
        return (T)o;

    }
    private static String buildKey(String clazzName, Object... args) {
        if (ArrayUtil.isEmpty(args)) {
            return clazzName;
        }
        return StrUtil.format("{}#{}", clazzName, ArrayUtil.join(args, "_"));
    }


    public static void main(String[] args) {
        try {
            Book abc = Singleton.get2(Book.class,"1","2");
            Book abcd = Singleton.get2(Book.class,"2","4");
            log.info(String.valueOf(abc==abcd));

            Book abcde = Singleton.get2(Book.class,"1","2");
            log.info(String.valueOf(abc == abcde));

            Book abcdef = Singleton.get2(null,"1","2");

        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }

}
